﻿#ifndef TL_STRING_H
#define TL_STRING_H

#include "Utility.h"


namespace TL {
    class String {
    public:
        static int my_strcmp(const char *left, const char *right)
        {
            int i;

            for(i = 0; left[i] && right[i]; i++) {
                if(left[i] < right[i])
                    return -1;
                else if(left[i] > right[i])
                    return 1;
            }
            
            if(!left[i] && right[i]) {
                return -1;
            } else if(left[i] && !right[i]) {
                return 1;
            } else {
                return 0;
            }
        }
        static void my_strcat(char *destString, const char *srcString)
        {
            int i = 0;

            while(destString[i])
                i++;

            for(int j = 0; srcString[j]; i++, j++)
                destString[i] = srcString[j];

            destString[i] = '\0';
        }
        static void my_strcpy(char *destString, const char *srcString)
        {
            int i;
            
            for(i = 0; srcString[i]; i++)
                destString[i] = srcString[i];

            destString[i] = '\0';
        }
        static int my_strlen(const char *srcString)
        {
            int i = 0;

            while(srcString[i])
                i++;

            return i;
        }
        
    public:
        String()
        {
            set_null();

            m_Ptr = new char [m_Size+1];

            my_strcpy(m_Ptr, "");
        }
        String(const char *string)
        {
            set_null();

            m_Size = my_strlen(string);

            m_Ptr = new char [m_Size+1];

            my_strcpy(m_Ptr, string);
        }
        String(const String &string)
        {
            set_null();

            m_Size = string.m_Size;

            m_Ptr = new char [m_Size+1];

            my_strcpy(m_Ptr, string.m_Ptr);
        }
        ~String()
        {
            delete [] m_Ptr;
        }
        
    public:
        const char &at(int index)
        {
            if(index < 0 || index > m_Size-1)
                return m_Undefined;

            return m_Ptr[index];
        }
        const char *getCharString()
        {
            return m_Ptr;
        }
        void reverse()
        {
            for(int i = 0; i < m_Size/2; i++) {
                TL::my_swap(&m_Ptr[i], &m_Ptr[m_Size-i-1]);
            }
        }
        const int &size()
        {
            return m_Size;
        }
        
    public:
#ifdef _IOSTREAM_
        friend std::ostream &operator<<(std::ostream &stream, const String &string)
        {
            stream << string.m_Ptr;

            return stream;
        }
#endif
        friend bool operator==(const char *string1, const String &string2)
        {
            return (my_strcmp(string1, string2.m_Ptr) == 0);
        }
        
    public:
        String &operator=(const char *string)
        {
            int string_size = my_strlen(string);

            if(m_Size != string_size) {
                m_Size = string_size;

                delete [] m_Ptr;
                m_Ptr = new char [m_Size+1];
            }

            my_strcpy(m_Ptr, string);

            return *this;
        }
        String &operator=(const String &string)
        {
            if(m_Size != string.m_Size) {
                m_Size = string.m_Size;

                delete [] m_Ptr;
                m_Ptr = new char [m_Size+1];
            }

            my_strcpy(m_Ptr, string.m_Ptr);

            return *this;
        }
        bool operator==(const char *string)
        {
            return (my_strcmp(m_Ptr, string) == 0);
        }
        bool operator==(const String &string)
        {
            return (my_strcmp(m_Ptr, string.m_Ptr) == 0);
        }
        char &operator[](int index)
        {
            return m_Ptr[index];
        }
    
    private:
        char *m_Ptr;
        char m_Undefined;
        int m_Size;

    private:
        void set_null()
        {
            m_Ptr = 0;
            m_Undefined = '\0';

            m_Size = 0;
        }
    };
}

#endif